package com.xiao.androidcompose01.viewmodel
import android.app.Application
import android.content.Intent
import android.os.Bundle
import androidx.core.content.PermissionChecker
import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import com.tencent.liteav.TXLiteAVCode
import com.tencent.map.geolocation.TencentLocation
import com.tencent.map.geolocation.TencentLocationListener
import com.tencent.map.geolocation.TencentLocationManager
import com.tencent.map.geolocation.TencentLocationRequest
import com.tencent.rtmp.ui.TXCloudVideoView
import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory
import com.tencent.tencentmap.mapsdk.maps.MapView
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory
import com.tencent.tencentmap.mapsdk.maps.model.LatLng
import com.tencent.tencentmap.mapsdk.maps.model.LatLngBounds
import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions
import com.tencent.tencentmap.mapsdk.maps.model.PolylineOptions
import com.tencent.trtc.TRTCCloud
import com.tencent.trtc.TRTCCloudDef
import com.tencent.trtc.TRTCCloudDef.TRTCScreenShareParams
import com.tencent.trtc.TRTCCloudDef.TRTCVideoEncParam
import com.tencent.trtc.TRTCCloudListener
import com.xiao.androidcompose01.api.data.AccountData
import com.xiao.androidcompose01.service.MediaService
import com.xiao.androidcompose01.viewmodel.TencentRoomModel.RoomState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.koin.core.annotation.Factory
import org.koin.core.annotation.Module
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

@Module
@Factory
class TencentRoomModel(
   private val application: Application,
   private val cloud: TRTCCloud,
) : StateScreenModel<RoomState>(RoomState.Idle),TencentLocationListener {
   
   init {
      cloud.addListener(CloudListener())
   }
   enum class MsgLevel{
      INFO,
      SUCCESS,
      ERROR
   }
   
   data class TencentCmdScreenData(
      val remoteUserId: String,
      val frame:TRTCCloudDef.TRTCVideoFrame,
      val streamType: Int
   )
   
   var cacheView: TXCloudVideoView? = null
   private val _tencentCmdScreen = MutableStateFlow<TencentCmdScreenData?>(null)
   val tencentCmdScreen = _tencentCmdScreen.asStateFlow()
   
   private val _tencentMsg = MutableStateFlow<Pair<MsgLevel, String>>(MsgLevel.INFO to "")
   val tencentMsg = _tencentMsg.asStateFlow()
   sealed class RoomState{
      data object Idle: RoomState()
      
      data class Success(val self: AccountData,val remoteUser: String?): RoomState()
      
      data class Failed(val msg: String): RoomState()
   }
   
   
   private inner class CloudListener: TRTCCloudListener(){
      
      override fun onError(errCode: Int, errMsg: String?, extraInfo: Bundle?) {
         TXLiteAVCode.ERR_SCREEN_CAPTURE_UNSURPORT
         if (errCode == -102015){
         
         }
         super.onError(errCode, errMsg, extraInfo)
      }
      
      override fun onRemoteVideoStatusUpdated(
         userId: String?,
         streamType: Int,
         status: Int,
         reason: Int,
         extraInfo: Bundle?
      ) {
         super.onRemoteVideoStatusUpdated(userId, streamType, status, reason, extraInfo)
         
      }
      
      override fun onSendFirstLocalVideoFrame(streamType: Int) {
         super.onSendFirstLocalVideoFrame(streamType)
      }
      override fun onMissCustomCmdMsg(userId: String?, cmdID: Int, errCode: Int, missed: Int) {
         super.onMissCustomCmdMsg(userId, cmdID, errCode, missed)
      }
      override fun onRemoteUserEnterRoom(userId: String?) {
         val state = mutableState.value
         if (state is RoomState.Success){
            mutableState.value = state.copy(state.self,userId)
            _tencentMsg.value = MsgLevel.SUCCESS to "$userId 加入直播间"
         }
      }
      
      override fun onRemoteUserLeaveRoom(userId: String?, reason: Int) {
         super.onRemoteUserLeaveRoom(userId, reason)
         val state = mutableState.value
         if (state is RoomState.Success){
            mutableState.value = state.copy(state.self,null)
         }
         _tencentMsg.value = MsgLevel.ERROR to "$userId 离开了直播间"
      }
      
      override fun onScreenCaptureStarted() {
         application.startService(Intent(application, MediaService::class.java))
      }
      override fun onRecvCustomCmdMsg(userId: String, cmdID: Int, seq: Int, message: ByteArray) {
         println("收到${userId}的消息${cmdID} ${String(message)}")
         cacheAccountData?.let {
            if (cmdID==1){
               val screen = TRTCScreenShareParams()
               val encParam = TRTCVideoEncParam()
               cloud.startScreenCapture(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SUB, encParam, screen)
               cloud.stopLocalAudio() //停止摄像头
            }
            if (cmdID==2){
               val trtcRenderParams = TRTCCloudDef.TRTCRenderParams()
               trtcRenderParams.fillMode = TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL //渲染模式为填充
               trtcRenderParams.mirrorType = TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_AUTO // 镜像类型为自动
               
               val cameraResult = PermissionChecker.checkSelfPermission(application,android.Manifest.permission.CAMERA)
               val audioResult = PermissionChecker.checkSelfPermission(application,android.Manifest.permission.RECORD_AUDIO)
               if (cameraResult == PermissionChecker.PERMISSION_GRANTED && audioResult == PermissionChecker.PERMISSION_GRANTED){
                  cacheView?.let {
                     cloud.startLocalPreview(true,cacheView)
                     val quality = TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT //默认：单声道；音频裸码率：50kbps；SDK 默认的音频质量，如无特殊需求推荐选择之。
                     TRTCCloudDef.TRTC_AUDIO_QUALITY_MUSIC //高音质：双声道 + 全频带；音频裸码率：128kbps；适合需要高保真传输音乐的场景，比如在线K歌、音乐直播等。
                     TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH //流畅：单声道；音频裸码率：18kbps；适合语音通话为主的场景，比如在线会议，语音通话。
                     cloud.stopScreenCapture() //先停止屏幕分享
                     cloud.startLocalAudio(quality)
                  }
               }else{
                  cloud.sendCustomCmdMsg(3,"用户未开启摄像头权限".toByteArray(),true,true)
               }
            }
            if (cmdID==3){
               val reply = TencentMsgUtils.filterMsg(cmdID,message)
               reply?.ifLocationSuccess {
                  processMap(this)
               }
            }
            if (cmdID==4){
               if (message.getOrNull(0)== 1.toByte()){
                  cloud.muteLocalAudio(true)
               }else{
                  cloud.muteLocalAudio(false)
               }
            }
            
//            if (cmdID==3){
//               _tencentMsg.value = MsgLevel.ERROR to message.toString(Charsets.UTF_8)
//            }
         }
      }
   }
   fun updateShowLocation(): String{
      val map = cacheMap?.map?:return "地图未初始化"
      if (cacheLocation.isEmpty())return "还未获得定位信息"
      val builder = LatLngBounds.builder()
      builder.include(cacheLocation)
      val factory = CameraUpdateFactory.newLatLngBounds(builder.build(),50)
      map.animateCamera(factory)
      return ""
   }
   private val cacheLocation = mutableListOf<LatLng>()
   private fun processMap(success: ChildReplyCmd.Location.Success) {
      println("收到地图信息:${success}")
      val latLng = LatLng(success.latitude,success.longitude)
      cacheLocation.add(latLng)
      val map = cacheMap?.map?:return
      map.clearAllOverlays()
      
//      val factory = CameraUpdateFactory.newLatLngBounds(builder.build(),50)
//      map.animateCamera(factory)
      val line = PolylineOptions()
      line.addAll(cacheLocation)
      line.borderWidth(1f)
      map.addPolyline(line)
      val marker = MarkerOptions(cacheLocation.last())
      marker.icon(BitmapDescriptorFactory.defaultMarker())
      map.addMarker(marker)
   }
   
   fun updateLocalView(){
      cloud.updateLocalView(cacheView)
   }
   
   fun cmdScreenCapture(){
      val state = mutableState.value
      if (state !is RoomState.Success){
         cacheAccountData?.let {
            screenModelScope.launch {
               enterRoom(it)
            }
         }
      }else{
         val cmdID = 1
         val data = byteArrayOf(0x01)
         val ordered = false //是否要求有序，即是否要求接收端的数据包顺序和发送端的数据包顺序一致（这会带来一定的接收延时）。
         val reliable = true //是否可靠发送，可靠发送可以获得更高的发送成功率，但可靠发送比不可靠发送会带来更大的接收延迟。
         val send = cloud.sendCustomCmdMsg(cmdID,data,ordered,reliable)
         if (send){
            _tencentMsg.value = MsgLevel.INFO to "向孩子发送了屏幕分享请求"
         }else{
            _tencentMsg.value = MsgLevel.ERROR to "向孩子发送了屏幕分享请求"
         }
      }
   }
   
   fun cmdCameraCapture(){
      val state = mutableState.value
      if (state !is RoomState.Success){
         cacheAccountData?.let {
            screenModelScope.launch {
               enterRoom(it)
            }
         }
      }else{
         val cmdID = 2
         val data = byteArrayOf(0x01)
         val ordered = false //是否要求有序，即是否要求接收端的数据包顺序和发送端的数据包顺序一致（这会带来一定的接收延时）。
         val reliable = true //是否可靠发送，可靠发送可以获得更高的发送成功率，但可靠发送比不可靠发送会带来更大的接收延迟。
         val send = cloud.sendCustomCmdMsg(cmdID,data,ordered,reliable)
         if (send){
            _tencentMsg.value = MsgLevel.INFO to "向孩子发送了查看摄像机请求"
         }else{
            _tencentMsg.value = MsgLevel.ERROR to "向孩子发送了查看摄像机请求"
         }
      }
   }
   
   
   private var cacheAccountData: AccountData? = null
   private var cacheMap: MapView? = null
   suspend fun enterRoom(account: AccountData){
      val cacheValue = mutableState.value
      if (cacheValue is RoomState.Success){
         return
      }
      this.cacheAccountData = account
      val roomParam = TRTCCloudDef.TRTCParams()
      roomParam.roomId = account.roomId.toInt()
      roomParam.sdkAppId = account.sdkAppId
      roomParam.userId = account.userId
      roomParam.userSig = account.tlsSig
      if (account.isParent()){
//         roomParam.role = TRTCCloudDef.TRTCRoleAudience
         roomParam.role = TRTCCloudDef.TRTCRoleAnchor
      }else{
         roomParam.role = TRTCCloudDef.TRTCRoleAnchor
      }
      val roomListener:TRTCCloudListener
      val joinRoomResult = suspendCoroutine<Boolean>{ joinRoom->
         roomListener = object : TRTCCloudListener(){
            override fun onEnterRoom(result: Long) {
               //加入房间成功
               val joinSuccess = result>=0
               joinRoom.resume(joinSuccess)
            }
            override fun onError(errCode: Int, errMsg: String, extraInfo: Bundle?) {
               super.onError(errCode, errMsg, extraInfo)
               mutableState.value = RoomState.Failed(errMsg)
            }
            
         }
         cloud.addListener(roomListener)
         cloud.enterRoom(roomParam, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL)
      }
      cloud.removeListener(roomListener)
      
      if (joinRoomResult){
         mutableState.value = RoomState.Success(account,null)
         if (account.isParent()){
            cloud.setRemoteVideoRenderListener(
               account.childIds[0],4,1,
               object : TRTCCloudListener.TRTCVideoRenderListener{
                  override fun onRenderVideoFrame(
                     remoteUserId: String,
                     streamType: Int,
                     frame: TRTCCloudDef.TRTCVideoFrame
                  ) {
                     _tencentCmdScreen.value = TencentCmdScreenData(remoteUserId,frame,streamType)
                  }
               })
         }
      }
   }
   data class UserController(
      val showCamera: Boolean,
      val playSound: Boolean
   )
   private val _userController = MutableStateFlow<UserController>(UserController(true,true))
   val userController = _userController.asStateFlow()
   
   fun muteVolume(isMute: Boolean){
      val r =
      if (isMute){
         cloud.sendCustomCmdMsg(4,byteArrayOf(1.toByte()),true,true)
      }else{
         cloud.sendCustomCmdMsg(4,byteArrayOf(0.toByte()),true,true)
      }
      println("发送命令:${r}")
      _userController.value = _userController.value.copy(playSound = isMute)
   }
   
   fun showOrHiddenCamera(isShow: Boolean){
      _userController.value = _userController.value.copy(showCamera = isShow)
   }
   
   
   
   fun startRemoteView(view:TXCloudVideoView){
      _tencentCmdScreen.value?.let {
         cloud.startRemoteView(
            it.remoteUserId,it.streamType,view
         )
      }
      
   }
   fun initMap(accountData: AccountData, mapView: MapView){
      cacheAccountData = accountData
      cacheMap = mapView
   }
   fun startLocation(accountData: AccountData, mapView: MapView?){
      cacheAccountData = accountData
      cacheMap = mapView
      if (!accountData.isParent()){ //只有子端才能够进行
         val request = TencentLocationRequest.create()
         request.interval = 1000
         TencentLocationManager.getInstance().requestLocationUpdates(request,this,0)
      }
   }
   private fun sendLocation(latitude: Double,longitude: Double,address: String,time: Long){
      TencentMsgUtils.sendLocation(cloud,latitude,longitude,address,time)
   }
   
   override fun onLocationChanged(
      location: TencentLocation?,
      code: Int,
      msg: String?
   ) {
      if (code==0 && location!=null){
//         println("--定位成功")
         sendLocation(location.latitude,location.longitude,location.address,location.time)
      }
   }
   
   override fun onStatusUpdate(p0: String?, p1: Int, p2: String?) {
   }
   
   override fun onGnssInfoChanged(p0: Any?) {
   }
   
   override fun onNmeaMsgChanged(p0: String?) {
   }
}